import 'package:dio/dio.dart';
import 'package:flutter_house_manager/constants/index.dart';
import 'package:flutter_house_manager/utils/Emitter.dart';
import 'package:flutter_house_manager/utils/TokenManager.dart';

class RequestDio {
  final _dio = Dio();
  // 1.主构造函数
  RequestDio() {
    //正常写法
    // 基地址
    // _dio.options.baseUrl = GlobalVariable.BASE_URL;
    // // 连接超时时间
    // _dio.options.connectTimeout =
    //     const Duration(seconds: GlobalVariable.NEW_WORK_TIME_OUT);
    // //接收超时时间
    // _dio.options.receiveTimeout =
    //     const Duration(seconds: GlobalVariable.NEW_WORK_TIME_OUT);

    //链式写法
    _dio.options
      ..baseUrl = GlobalVariable.BASE_URL
      ..connectTimeout =
          const Duration(seconds: GlobalVariable.NEW_WORK_TIME_OUT)
      ..receiveTimeout =
          const Duration(seconds: GlobalVariable.NEW_WORK_TIME_OUT);

    // 添加拦截器
    _dio.interceptors.add(InterceptorsWrapper(
      onRequest: (context, handler) {
        // 请求拦截器
        // 注入token
        String token = tokenManager.getToken();
        if (token.isNotEmpty) {
          context.headers["Authorization"] = 'Bearer $token';
        }
        handler.next(context);
      },
      // 响应拦截器
      onResponse: (context, handler) {
        // 状态码判断
        if (context.statusCode! >= 200 && context.statusCode! <= 300) {
          handler.next(context);
        } else {
          handler.reject(DioException(requestOptions: context.requestOptions));
        }
      },
      // 错误拦截器
      onError: (context, handler) async {
        //处理401错误码
        if (context.response!.statusCode == 401) {
          // 1.判断是否有refreshToken
          String refreshToken = tokenManager.getRefreshToken();
          if (refreshToken.isNotEmpty) {
            try {
              // 1.获取新的token
              await _refresh();
              // 2.刷新成功，重新进行上一次失败的请求(无感请求)
              return handler.resolve(await _dio.fetch(context.requestOptions));
            } on Exception catch (e) {
              eventBus.fire(LogoutEvent(e.toString()));
            }
          } else {
            //不能直接跳转，因为无法获取到所需的上下文
            //采用类似消息通知的方式 evevtBus
            eventBus.fire(LogoutEvent('401,未授权'));
          }
        }
        handler.reject(context);
      },
    ));
  }

  // 刷新token
  _refresh() async {
    // 1.获取refreshToken
    String refreshToken = tokenManager.getRefreshToken();
    // 2.创建新的Dio实例
    Dio newDio = Dio();
    // 3.请求
    final res = await newDio.post(
      '${GlobalVariable.BASE_URL}${HTTP_PATH.REFRESH_TOKEN}',
      options: Options(
        headers: {"Authorization": 'Bearer $refreshToken'},
      ),
    );
    // 4.存储新的token和refreshToken
    tokenManager.setToken(res.data['data']['token'],
        refreshToken: res.data['data']['refreshToken']);
  }

  // 2.定义方法
  get(String url, {Map<String, dynamic>? params}) {
    return _handleRes(_dio.get(url, queryParameters: params));
  }

  post(String url, {Map<String, dynamic>? data}) {
    return _handleRes(_dio.post(url, data: data));
  }

  put(String url, {Map<String, dynamic>? data}) {
    return _handleRes(_dio.put(url, data: data));
  }

  delete(String url,
      {Map<String, dynamic>? params, Map<String, dynamic>? data}) {
    return _handleRes(_dio.delete(url, queryParameters: params, data: data));
  }

  //上传
  upload(String url, {FormData? data}) {
    return _handleRes(_dio.post(url, data: data));
  }

  // 3.数据剥离
  _handleRes(Future<Response<dynamic>> task) async {
    final res = await task;
    // 请求成功
    if (res.data['code'] == GlobalVariable.SUCCESS_CODE) {
      return res.data['data'];
    }
    // 请求失败
    throw DioException(requestOptions: res.requestOptions);
  }
}

final RequestDio requestDio = RequestDio();
